初期化済変数はエクスポートできなかっただけという話。 未初期化の変数をエクスポートしてロード時に代入すればOK。 首の皮1枚でつながった。
まあ俺自身は本当にできるかどうかの確認まではしてないけどな。
初期化済変数はエクスポートできなかっただけという話。 未初期化の変数をエクスポートしてロード時に代入すればOK。 首の皮1枚でつながった。
まあ俺自身は本当にできるかどうかの確認まではしてないけどな。
オワタ\(^O^)/
ことの始まりは「俺のライブラリがFirefox4で使えない(意訳・超要約)」なるメールが届いたこと。 どうやらFirefox4からはXPCOMコンポーネントの呼び出し方法が若干変わるようだ。 で、XPCOM changes in Gecko 2.0を調べてみると、どうもDLLから変数のエクスポートをしなければならないらしい。 だが、Delphiは関数のエクスポートはできても変数のエクスポートができない。
はい、終了。
もともと最近は興味が縮小して放置状態だったとはいえ、この変更は致命的な致命傷だ。 何とかしたいところだが現状では前の方法に戻してくれとコミットするしかないな。 こんな理由でBugzilla初投稿なるのか?いやだなあ。
GeckoSDK for DelphiのコードをBagelブラウザによる変更を一部マージするなどして更新した。 Begelの新バージョンはDelphiを使わないようなので、もう更新は俺が頑張るしかないんだよな。
それはそうとBegelがDelphiの採用をやめた理由のひとつに、Mozilla 2でのAPIの大幅変更がある。 C++例外を前提にしたコードになるので、フレームワークのまったく違うDelphiでの対応は確かに難しい。 よほど変態的なコードでラッパを書かないことには新APIでは動かすこともままならないだろう。
で、どんな変態的ラッパを書かねばならないかと、新APIのコードを確認してみたかったのだが、 いかんせんソースツリーにその正体が現れてこない。 Mozilla-centralのコードは旧態依然としたGecko 1.9ベースのコードのままだ。 Mozilla 2のAPIが新しくなるのは2006年には発表されていたので、 かれこれ2年以上もその姿が見えていないことになる。
目標の向かう方向はわかるものの、その行く先がはっきりしないのではどうしようもない。 しばらくはGecko 1.xベースのままでコードは保守されていくだろう。 Gecko 2の開発期間がGecko 1.0より長くなりませんように。
Delphi 2009を買った結果がこれだよ!
若干放置気味になっているGecko SDK for DelphiをDelphi 2009に対応すべく コードの修正を開始した。 しかしこれが大変だ。 Delphi 2009はDelphiで初めてRTLとVCLがすべてUnicode対応にしたため、 というかむしろUnicodeを標準にしたため、 過去のコードの修正が結構大変なことになってきた。 基本ASCII文字列しか扱えないURL周りの処理はともかく、 MBCSでもUnicodeでもどちらでもいけるファイル関係の処理は 今後の設計ポリシーにも関わることなので慎重にいかねばならない。
というかそんなこと考えている暇があるならまずコードの内容を充実させろよ。
Gecko 1.7以前はGeckoの初期化をするために、xpcom.dll
内の
NS_InitXPCOM2
を呼び出す必要があった。
この関数の引数にはnsIDirectoryServiceProvider
を指定する必要があり、
しかもこのインターフェースはGREの
場所を返せないといけない。
はっきり行って面倒くさい。
ちゃんと動作させないと一部のインターフェースが動いてくれないので、
面倒くさいが必須の作業なのだ。
まあ面倒くさい。
このインターフェースを含む初期化処理を行う関数を自作ライブラリに用意しているのだが、
初期化用ライブラリのため暗黙の動的メモリ確保を使用するコードを書きたくなかったので、
とても神経を使った。
ていうかNewInstance
クラスメソッドとかはじめて使った。
一方、Gecko 1.8以降には追加関数としてXRE_InitEmbedding
が用意された。
こいつはxul.dll
内にある関数なのだが、
非常に面倒くさいnsIDirectoryServiceProvider
の実装を
肩代わりしてくれている点において、非常にありがたい。
まあこの関数をxul.dll
から持ってくるコードを書かないといけないわけだが、
インターフェースの実装よりははるかに簡単だ。
Gecko内部の関数なので、Geckoの仕様が変わったりとかで初期化の仕方が変わっても、
ちゃんと追従できるのがうれしい。
こういう関数をもっと早く用意してくれれば無駄なコードを核時間が減るんだけどなあ。
そういえば以前nsAString
の実装をDelphiで実現したな。
Gecko 1.7でNS_StringContainerInit
その他が実装されたときには、
血の涙を流して喜んだものだ。
nsIWebBrowserのガワの話。 要するにnsIWebBrowserChromeの実装の話。 とりあえず触りだけ。
最低限以下のインターフェースの実装が必要なようだ。
nsIWebBrowserChrome
ガワ本体。ガワなのに本体とはどういうことかと思うが
nsIWebBrowser.containerWindow
が
nsIWebBrowserChrome
型なので仕方ない。
nsIInterfaceRequestor
今ひとつどう説明すればわからないインターフェース。
queryInterface
によく似たメソッドgetInterface
を持つ。
getInterface
で取得したインターフェースは逆変換できる必要はない。
queryInterface
ではあくまで自分自身を返すが、
getInterface
ではプロパティや関数の戻り値を返してもいいことになる。
Mozillaのソースを深く読んではいないのでどう便利なのかはいまいちわからないが、
nsIWebBrowser
のガワとしては必須。
とりあえず上の2つのインターフェースのメンバのうち、
nsIInterfaceRequestor.getInterface
メソッドを
queryInterface
に丸投げして
nsIWebBrowserChrome.webBrowser
プロパティを実装すれば
残りのメソッドは全部NS_ERROR_NOT_IMPLEMENTED
にしても動く。
getInterface
を実装しないとFlashもまともに表示されないしリンクも飛べない。
でもgetInterface
さえ実装すれば動く。
それくらい重要。
はっきり言ってGecko Embedding BasicsにnsIInterfaceRequestor
がないのは詐欺だろ。
続・nsIHttpChannel.asyncOpenが動かないの続き。
nsIHttpChannel.asyncOpen
および
nsIStreamListener
がらみのソースを追っていったところ、
どうやらNS_ProcessNextEvent
なる関数が怪しいことがわかった。
この関数は現在のスレッドに対して
nsIThread.processNextEvent(PR_False)
を呼び出す。
こうすることで現在のスレッドにたまっているGeckoイベントを処理することができるわけだ。
こいつを呼び出す処理をたとえばDelphiならApplication.OnIdle
に追加すればいい。
が、Gecko1.8まではそんなことをせずともイベントを処理できていたので改悪に見えなくもない。 せっかくのイベント駆動型のOSを使っているのに こんな余計な処理を埋め込みたくないというのが正直な感想だ。 一応Gecko1.9でもSimpleDownload他を動かせる目処が立ったので、 とりあえずそれはよしとする。
まさかnsIWebBrowser
のリスナーでも必要だとか言うことはないだろうな。
30分で「続」とかないわ。
nsIHttpChannel.asyncOpenが動かないの続き。 Mozillaおよびxulrunnerのbinフォルダに直接SimpleDownloadをぶち込んで動作確認をした。
タイトルのごとく。 nsIHttpChannelが動かないわけじゃなくてnsIHttpChannel.asyncOpenが動かない。 nsIHttpChannel.openは問題なく使用可能だったのだが、 nsIHttpChannel.asyncOpenはなぜか動作しない。 引数のaListenerもプロパティのnotificationCallbacksのほうにもgetInterfaceはおろか QueryInterfaceすら呼び出されない。 つまり当然コールバックがないのでデータの読み込みは不可・・・。 SimpleDownloadでも、xpcshellでもだめなので原因がいまいちよくわからない。 SimpleDownloadを作ったときには動いていたので、Geckoのバージョンがあがったので仕様が変わったのだろうか? Frozenインターフェースのはずだからそれはないと思いたい。
以上、メモというより愚痴終わり。
6年位前に通過したことをいまさら記録として残してみるテスト。
begin
{ 初期化 }
XPCOMGlueStartup(xpcomPath);
XPCOMGlueLoadXULFunctions(@xulFunctions);
XRE_InitEmbedding(xpcomDir, nil, nil, nil, 0);
{ WebBrowserオブジェクトの作成 }
NS_CreateInstance(NS_WEBBROWSER_CONTRACTID, nsIWebBrowser, browser);
baseWin := browser as nsIBaseWindow;
baseWin.InitWindow(Pointer(hWnd), nil, 0, 0, rcClient.Right, rcClient.Bottom);
baseWin.Create();
baseWin.SetVisibility(PR_True);
{ ページ読み込み }
navigation := browser as nsINavigation;
navigation.LoadURI('http://nesitive.net/nesitive/', 0, nil, nil, nil);
{ 気が済んだら終了 }
XRE_TermEmbedding();
// XPCOMGlueShutdown(); // なぜかエラーになる
end.